package org.mj.hz.http;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.http.ContentType;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.Method;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import lombok.Data;
import org.apache.commons.lang3.ClassUtils;

import java.util.*;
import java.util.concurrent.LinkedBlockingDeque;

@Data
public class BaseRequest {
    /**
     * 请求地址
     */
    private String baseUrl;

    /**
     * 请求路径
     */
    private String path;



    /**
     * 请求体
     */
    private JSONObject jsonObject;


    /**
     * 请求contentType
     */
    private ContentType contentType;




    private MjPreRequest mjPreRequest;


    private HttpRequest httpRequest;


    public BaseRequest() {
        mjPreRequest = new MjPreRequest();
    }

    /**
     * 构建请求
     *
     * @param args
     * @return
     */
    public HttpRequest makeRequest(Object[] args) {
        return buildRequestMode(args);
    }


    private HttpRequest buildRequestMode(Object[] args) {
        this.httpRequest.setConnectionTimeout(100000);
        buildHeader( this.httpRequest, args);
        buildParamMode( this.httpRequest, args);
        return  this.httpRequest;
    }

    /**
     * 构建参数
     *
     * @param httpRequest
     * @param args
     */
    private void buildParamMode(HttpRequest httpRequest, Object[] args) {
        String contentType = httpRequest.header("Content-Type");
        if (StrUtil.isNotEmpty(contentType)) {
            if (contentType.equals(ContentType.JSON.getValue())) {
                httpRequest.body(JSONUtil.toJsonStr(args[0]));
            } else if (contentType.equals(ContentType.TEXT_PLAIN.getValue())) {
                appendParamUrl(httpRequest,buildParam(args));
            }
        } else {
            Method method = httpRequest.getMethod();
            if (method.equals(Method.POST)) {
                httpRequest.body(JSONUtil.toJsonStr(args[0]));
            } else if (method.equals(Method.GET)) {
                appendParamUrl(httpRequest,buildParam(args));
            }
        }
    }

    /**
     * 拼接map到url上
     * @param request
     * @param map
     */
    private void appendParamUrl(HttpRequest request, Map<String, Object> map) {
        String url = request.getUrl();
        //拼接url

        if (CollUtil.isNotEmpty(map)) {
            StringBuffer stringBuffer = new StringBuffer();

            Set<Map.Entry<String, Object>> entries = map.entrySet();
            LinkedBlockingDeque<Map.Entry<String, Object>> blockingDeque = new LinkedBlockingDeque<>(entries);
            Map.Entry<String,Object> temp = null;

            while (ObjectUtil.isNotNull(temp = blockingDeque.poll())) {
                stringBuffer.append(temp.getKey());
                stringBuffer.append("=");
                stringBuffer.append(temp.getValue());
                if (!blockingDeque.isEmpty()) {
                    stringBuffer.append("&");
                }
            }
            request.setUrl(url + "?" + stringBuffer);

        }
    }

    private Map<String, Object> buildParam(Object[] args) {
        return getHttpParamMap(args, this.mjPreRequest.getParamMap());
    }

    private void buildHeader(HttpRequest request, Object[] args) {
        Map<String, Object> tempMap = getHttpHeaderMap(args, this.getMjPreRequest().getHeaderMap());
        if (CollUtil.isNotEmpty(tempMap)) {
            Map<String, String> map = new HashMap<String, String>();
            for (String i : tempMap.keySet()) {
                map.put(i, String.valueOf(tempMap.get(i)));
            }
            request.headerMap(map, false);
        }
    }

    /**
     * 参数组装
     * @param args
     * @param map
     * @return
     */
    private Map<String, Object> getHttpParamMap(Object[] args, Map<Integer, Object> map) {
        Map<String, Object> resMap = new HashMap<>();
        if (null != args) {

            for (int i = 0; i < args.length; i++) {
                if (map.containsKey(i)) {
                    if (ClassUtils.isPrimitiveOrWrapper(args[i].getClass()) ||  args[i].getClass().equals(String.class)) {
                        if (CollUtil.isNotEmpty(map)) {
                            resMap.put(String.valueOf(map.get(i)), args[i]);
                        }
                    } else {
                        resMap.putAll(BeanUtil.beanToMap(args[i], false, true));
                    }
                }
            }
        }
        return resMap;
    }

    /**
     * header 组装
     * @param args
     * @param map
     * @return
     */
    private Map<String, Object> getHttpHeaderMap(Object[] args, Map<Integer, Object> map) {
        Map<String, Object> resMap = new HashMap<>();
        if (null != args) {
            for (int i = 0; i < args.length; i++) {
                if (map.containsKey(i)){
                    if (ClassUtils.isPrimitiveOrWrapper(args[i].getClass()) || args[i].getClass().equals(String.class)) {
                        if (CollUtil.isNotEmpty(map)) {
                            resMap.put(String.valueOf(map.get(i)), args[i]);
                        }
                    }
                }

            }
        }
        return resMap;
    }

}
